import pygame
import sys
import random
import os

# 游戏配置
SIZE = 4  # 4x4棋盘
TILE_SIZE = 100
TILE_MARGIN = 16
WIDTH = SIZE * TILE_SIZE + (SIZE + 1) * TILE_MARGIN
HEIGHT = WIDTH + 100  # 额外空间显示分数
FPS = 60

# 颜色配置
BACKGROUND_COLOR = (250, 248, 239)
EMPTY_TILE_COLOR = (205, 193, 180)
TILE_COLORS = {
    2: (238, 228, 218),
    4: (237, 224, 200),
    8: (242, 177, 121),
    16: (245, 149, 99),
    32: (246, 124, 95),
    64: (246, 94, 59),
    128: (237, 207, 114),
    256: (237, 204, 97),
    512: (237, 200, 80),
    1024: (237, 197, 63),
    2048: (237, 194, 46),
}
FONT_COLOR = (119, 110, 101)
FONT_COLOR_LIGHT = (249, 246, 242)
SCORE_COLOR = (119, 110, 101)
GAME_OVER_COLOR = (238, 68, 56)

pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('2048 by Pygame')
clock = pygame.time.Clock()

# 字体设置，支持中文
def get_chinese_font(size, bold=False):
    # 常见中文字体，优先使用微软雅黑
    font_paths = [
        os.path.join(os.environ.get('WINDIR', 'C:/Windows'), 'Fonts', 'msyh.ttc'),  # 微软雅黑
        os.path.join(os.environ.get('WINDIR', 'C:/Windows'), 'Fonts', 'simhei.ttf'), # 黑体
        os.path.join(os.environ.get('WINDIR', 'C:/Windows'), 'Fonts', 'simsun.ttc'), # 宋体
    ]
    for path in font_paths:
        if os.path.exists(path):
            return pygame.font.Font(path, size)
    return pygame.font.SysFont('arial', size, bold=bold)

font = get_chinese_font(36, bold=True)
tile_font = get_chinese_font(40, bold=True)
score_font = get_chinese_font(28, bold=True)
instruction_font = get_chinese_font(18, bold=False)

def draw_board(board, score, game_over):
    screen.fill(BACKGROUND_COLOR)
    # 绘制分数
    score_text = score_font.render(f'Score: {score}', True, SCORE_COLOR)
    screen.blit(score_text, (TILE_MARGIN, WIDTH + 20))
    # 绘制操作说明（字体更小，位置更下方）
    instruction = '方向键/WASD移动  R重开  ESC退出'
    instruction_text = instruction_font.render(instruction, True, SCORE_COLOR)
    instruction_rect = instruction_text.get_rect(centerx=WIDTH // 2, centery=WIDTH + 80)
    screen.blit(instruction_text, instruction_rect)
    # 绘制棋盘
    for row in range(SIZE):
        for col in range(SIZE):
            value = board[row][col]
            rect = pygame.Rect(
                TILE_MARGIN + col * (TILE_SIZE + TILE_MARGIN),
                TILE_MARGIN + row * (TILE_SIZE + TILE_MARGIN),
                TILE_SIZE, TILE_SIZE)
            color = TILE_COLORS.get(value, EMPTY_TILE_COLOR) if value else EMPTY_TILE_COLOR
            pygame.draw.rect(screen, color, rect, border_radius=8)
            if value:
                text_color = FONT_COLOR if value <= 4 else FONT_COLOR_LIGHT
                text_surface = tile_font.render(str(value), True, text_color)
                text_rect = text_surface.get_rect(center=rect.center)
                screen.blit(text_surface, text_rect)
    # 游戏结束提示
    if game_over:
        overlay = pygame.Surface((WIDTH, WIDTH), pygame.SRCALPHA)
        overlay.fill((255, 255, 255, 180))
        screen.blit(overlay, (0, 0))
        over_text = font.render('Game Over!', True, GAME_OVER_COLOR)
        over_rect = over_text.get_rect(center=(WIDTH // 2, WIDTH // 2 - 30))
        screen.blit(over_text, over_rect)
        restart_text = score_font.render('Press R to Restart', True, GAME_OVER_COLOR)
        restart_rect = restart_text.get_rect(center=(WIDTH // 2, WIDTH // 2 + 30))
        screen.blit(restart_text, restart_rect)
    pygame.display.flip()

def init_board():
    board = [[0] * SIZE for _ in range(SIZE)]
    add_random_tile(board)
    add_random_tile(board)
    return board

def add_random_tile(board):
    empty = [(r, c) for r in range(SIZE) for c in range(SIZE) if board[r][c] == 0]
    if empty:
        r, c = random.choice(empty)
        board[r][c] = 4 if random.random() < 0.1 else 2

def compress(row):
    new_row = [i for i in row if i != 0]
    new_row += [0] * (SIZE - len(new_row))
    return new_row

def merge(row):
    score = 0
    for i in range(SIZE - 1):
        if row[i] != 0 and row[i] == row[i + 1]:
            row[i] *= 2
            score += row[i]
            row[i + 1] = 0
    return row, score

def move_left(board):
    moved = False
    score = 0
    new_board = []
    for row in board:
        compressed = compress(row)
        merged, add_score = merge(compressed)
        compressed = compress(merged)
        if compressed != row:
            moved = True
        new_board.append(compressed)
        score += add_score
    return new_board, moved, score

def rotate_board(board):
    return [list(row) for row in zip(*board[::-1])]

def move(board, direction):
    # direction: 'left', 'right', 'up', 'down'
    rotated = board
    for _ in range({'left': 0, 'up': 1, 'right': 2, 'down': 3}[direction]):
        rotated = rotate_board(rotated)
    moved_board, moved, score = move_left(rotated)
    for _ in range((4 - {'left': 0, 'up': 1, 'right': 2, 'down': 3}[direction]) % 4):
        moved_board = rotate_board(moved_board)
    return moved_board, moved, score

def can_move(board):
    for row in board:
        for i in range(SIZE - 1):
            if row[i] == 0 or row[i] == row[i + 1]:
                return True
    for col in range(SIZE):
        for row in range(SIZE - 1):
            if board[row][col] == 0 or board[row][col] == board[row + 1][col]:
                return True
    return False

def main():
    board = init_board()
    score = 0
    game_over = False
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
                if event.key == pygame.K_r:
                    board = init_board()
                    score = 0
                    game_over = False
                if not game_over:
                    if event.key in (pygame.K_LEFT, pygame.K_a):
                        new_board, moved, add_score = move(board, 'left')
                    elif event.key in (pygame.K_RIGHT, pygame.K_d):
                        new_board, moved, add_score = move(board, 'right')
                    elif event.key in (pygame.K_UP, pygame.K_w):
                        new_board, moved, add_score = move(board, 'up')
                    elif event.key in (pygame.K_DOWN, pygame.K_s):
                        new_board, moved, add_score = move(board, 'down')
                    else:
                        continue
                    if moved:
                        board = new_board
                        score += add_score
                        add_random_tile(board)
                        if not can_move(board):
                            game_over = True
        draw_board(board, score, game_over)
        clock.tick(FPS)

if __name__ == '__main__':
    main() 